﻿using System;
using System.Collections.Generic;
using System.Linq;
using COFE.Core;
using COFE.Core.Lister;
using COFE.Core.Profile;
using COFE.Core.Utils;
using NUnit.Framework;
using COFE.Core.Entry;

namespace COFE.Data.DBLink
{
    public class DBLinkDirectoryLister : PrimaryDirectoryListerBase<COFE.Data.Entry>
    {
        #region Constructor

        public DBLinkDirectoryLister(IFactory<IDirectoryLister> factory, string listerKey)
            : base(factory, listerKey)
        {



            _getRootDirectory = () =>
                {
                    if (!(COFEDBShared.DBEntryManager.Exists(rootPath)))
                    {
                        //Construct a new volume.
                        COFEDBShared.DBEntryManager.UpdateEntry(
                            new DBLinkTempPropertyProvider(listerKey));
                    }

                    return COFEDBShared.DBOperations.ReadDatabase(
                        (context) => COFEDBShared.DBEntryManager.LookupEntry(context, rootPath),
                        (context, rootEntry) =>
                        {
                            return new Entry[] { rootEntry };
                        });

                };

            //_parse = (fullParsePath) =>
            //    {
            //        string listerKey, parsePath;
            //        COFEPath.ParseFullParseName(
            //    };

        }

        #endregion

        #region Methods

        public override IFileSystemInfo ParsePath(string path, EntryConstructionFlags flags)
        {
            if (flags.HasFlag(EntryConstructionFlags.VolumeKeyNotDefined))
                return null;

            IFileSystemInfo retVal = null;

            string fullParsePath = COFEPath.FormatFullParseName(this.ListerKey, path);
            COFEDBShared.DBOperations.UpdateDatabase(
                (context) => COFEDBShared.DBEntryManager.LookupEntry(context, fullParsePath),
                (context, dbEntry) =>
                {                    
                    if (dbEntry == null && String.IsNullOrEmpty(path))
                    {
                        COFEDBShared.DBEntryManager.UpdateEntry(new DBLinkTempPropertyProvider(this.ListerKey));
                        dbEntry = COFEDBShared.DBEntryManager.LookupEntry(context, fullParsePath);
                    }
                    if (dbEntry != null)
                        retVal = COFEShared.EntryConstructor.CreateEntry(CreatePropertyProvider(dbEntry), flags);
                });
            
            return retVal;
        }

        public override IInternalDirectoryInfoExA GetParent(IInternalFileSystemInfoExA entry)
        {
            string listerKey, parsePath;
            COFEPath.ParseFullParseName(entry.ParseName, out listerKey, out parsePath);

            Assert.AreEqual(ListerKey, listerKey);
            if (parsePath == "")
                return COFEShared.CurrentUserProfile.ProfileRootDirectory as IInternalDirectoryInfoExA;

            string parentParsePath = COFEPath.GetDirectoryName(parsePath);
            return COFEShared.CurrentUserProfile.TryParsePath(COFEPath.Combine(listerKey, parentParsePath), EntryConstructionFlags.Default) as IInternalDirectoryInfoExA;
        }


        public override IEnumerable<IFileSystemInfo> List(IInternalDirectoryInfoExA parent, EntryConstructionFlags flags)
        {
            Func<IFileSystemInfo, IFileSystemInfo> createRedirect = (entry) =>
                {
                    return RedirectPropertyProvider.CreateRedirectEntry(parent, entry);
                };

            string parentParseName = parent.GetParseNameOrDefault();
            var parentEntry = getEmbeddedItem(parent);

            COFEDBShared.DBOperations.ReadDatabase((context) =>
                {
                    parentEntry = context.Entries.Include("Children")
                        .FirstOrDefault((e) => e.EntryId == parentEntry.EntryId);
                });

            IEnumerator<IFileSystemInfo> etor = null;
            Assert.AreEqual(ListerKey, parentEntry.PrimaryVolumeId);

            foreach (var child in parentEntry.Children)
                yield return COFEShared.EntryConstructor.CreateEntry(new DBLinkPropertyProvider(child), flags);

            var entryList = COFEShared.EntryListRegistrar.GetDBLinkEntryList(COFEShared.CurrentUserProfile, parentEntry);
            etor = entryList.Entries.GetEnumerator();

            if (etor != null)
                while (etor.MoveNext())
                    yield return createRedirect(etor.Current);
        }


        public override IPropertyProvider CreatePropertyProvider(Entry item)
        {
            return new DBLinkPropertyProvider(item);
        }


        public override IDirectoryController CreateController()
        {
            return new DBLinkDirectoryController(this);
        }

        public override IStreamProvider CreateStreamProvider()
        {
            return new DBLinkStreamProvider(this);
        }

        #endregion

        #region Data


        #endregion

        #region Public Properties

        private string rootPath { get { return String.Format("{{{0}}}", ListerKey); } }


        #endregion
    }
}
